#include "include/download.h"

#include <Wt/WTable>
#include <Wt/WComboBox>
#include <Wt/WText>
#include <Wt/WPushButton>
#include <Wt/WAnchor>
#include <Wt/WApplication>
#include <Wt/WEnvironment>

#include <iostream>
#include <fstream>
#include <sstream>

#include <vector>

#include <algorithm>

#ifndef BOOST_FILESYSTEM_VERSION
#define BOOST_FILESYSTEM_VERSION 2
#endif

#include <boost/filesystem.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

using namespace boost::filesystem;
using namespace Wt;
using namespace std;

Download::Download() :
	WContainerWidget(0),
	m_activatedLevel(-1),
	m_currentPath("./releases/"),
	m_paths(6),
	m_row(0),
	m_combos(6)
{
	addWidget(new WText(tr("home.download")));

	addWidget(new WText(tr("mu.screenshot")));

	addWidget(new WText(tr("home.spacer.vertical")));

	m_beginVersionSelection = new Wt::WPushButton("Download");

	addWidget(m_beginVersionSelection);

	m_pDownloadOSText = new WText(tr("home.download.selectOS"));
	addWidget(m_pDownloadOSText);
	m_pDownloadOSText->hide();

	addWidget(new WText(tr("home.spacer.vertical")));

	m_pTable = new WTable(this);

	m_paths[0] = "./releases/";

	for (size_t i = 0; i < 6; i++)
	{
		m_combos[i] = new WComboBox(m_pTable->elementAt(0, m_row++));
		m_combos[i]->hide();
	}

	m_pReleaseText = new WText();

	addWidget(m_pReleaseText);

	m_downloadButton = new Wt::WPushButton("Begin Download");
	m_downloadButton->hide();

	m_downloadButton->clicked().connect(this, &Download::performDownload);

	addWidget(m_downloadButton);

	addWidget(new WText(tr("home.spacer.vertical")));

	m_beginVersionSelection->clicked().connect(this, &Download::downloadClicked);

	m_combos[0]->activated().connect(this, &Download::pickedL0);
	m_combos[1]->activated().connect(this, &Download::pickedL1);
	m_combos[2]->activated().connect(this, &Download::pickedL2);
	m_combos[3]->activated().connect(this, &Download::pickedL3);
	m_combos[4]->activated().connect(this, &Download::pickedL4);
	m_combos[5]->activated().connect(this, &Download::pickedL5);

	addWidget(new WText(tr("home.intro")));
}

void Download::pickedL0()
{
	m_activatedLevel = 0;
	comboActivated();
}

void Download::pickedL1()
{
	m_activatedLevel = 1;
	comboActivated();
}

void Download::pickedL2()
{
	m_activatedLevel = 2;
	comboActivated();
}

void Download::pickedL3()
{
	m_activatedLevel = 3;
	comboActivated();
}

void Download::pickedL4()
{
	m_activatedLevel = 4;
	comboActivated();
}

void Download::pickedL5()
{
	m_activatedLevel = 5;
	comboActivated();
}

void Download::ls(path p, pair<vector<boost::filesystem::path>, vector<boost::filesystem::path> >& ret)
{
	try
	{
		if(exists(p))
		{
			if(is_regular_file(p))
			{

			}
			else if(is_directory(p))
			{
				directory_iterator dir_iter(p), dir_end;
				for(;dir_iter != dir_end; ++dir_iter)
				{
					if (is_directory(*dir_iter))
						ret.second.push_back(*dir_iter);
					else if (is_regular_file(*dir_iter))
						ret.first.push_back(*dir_iter);
				}
			}
		}
	}

	catch(const filesystem_error& ex)
	{
		cerr << ex.what() << '\n';
	}
}

void Download::comboActivated()
{
	if (m_activatedLevel != -1)
	{
		string text = m_combos[m_activatedLevel]->currentText().toUTF8();
		if (text == "")
		{
			clearFutureCombos();
			cleanReleaseNotes();
			return;
		}
		m_paths[m_activatedLevel + 1] = text;
	}

	m_paths.resize(m_activatedLevel + 2);

	m_currentPath = "./releases";

	for (int i = 0; i < m_activatedLevel+1; i++)
		m_currentPath = m_currentPath.string() + string("/") + string(m_combos[i]->currentText().toUTF8());

	pair<vector<path>, vector<path> > p;

	ls(m_currentPath, p);

	clearFutureCombos();

	bool hasDirs = p.second.size() != 0;
	bool hasFiles = p.first.size() != 0;

	if (hasDirs)
	{
		m_combos[m_activatedLevel+1]->addItem("");
		m_combos[m_activatedLevel+1]->show();

		for (vector<path>::iterator it = p.second.begin(); it != p.second.end(); it++)
		{
#if BOOST_FILESYSTEM_VERSION == 3
			m_combos[m_activatedLevel + 1]->addItem(it->filename().string());
#elif BOOST_FILESYSTEM_VERSION == 2
						m_combos[m_activatedLevel + 1]->addItem(it->filename());
#endif
		}

		cleanReleaseNotes();
	}
	else if (hasFiles)
		displayReleaseNotes(p.first);

}

void Download::clearFutureCombos()
{
	for (size_t i = m_activatedLevel + 1; i < 6; i++)
	{
		m_combos[i]->clear();
		m_combos[i]->hide();
	}
}

void Download::readReleaseNotes(boost::filesystem::path p, std::string& text) const
{
	string line;
	ifstream myfile (p.string().c_str());
	if (myfile.is_open())
	{
	  while ( myfile.good() )
	  {
		getline (myfile,line);
		text += line;
	  }
	  myfile.close();
	}
}

void Download::displayReleaseNotes(const vector<path>& v)
{
	path releaseNotes;
	for (vector<path>::const_iterator it = v.begin(); it != v.end(); it++)
	{

#if BOOST_FILESYSTEM_VERSION == 3
				if (string::npos != it->filename().string().find("release_notes"))
#elif BOOST_FILESYSTEM_VERSION == 2
				if (string::npos != it->filename().find("release_notes"))
#endif
			releaseNotes = *it;
		else
			m_fileToDownload = *it;
	}

	string text = "<br style=\"clear: both\" /><h4>Release Notes</h4>";

	readReleaseNotes(releaseNotes, text);

	text += "<br/><br/>";

	m_pReleaseText->setText(text);
	m_pReleaseText->refresh();

	m_downloadButton->show();
}

void Download::cleanReleaseNotes()
{
	m_pReleaseText->setText("");
	m_pReleaseText->refresh();
	m_downloadButton->hide();
}

void Download::downloadClicked()
{
	m_combos[0]->show();
	m_pDownloadOSText->show();
	comboActivated();
}

void Download::messageBoxDone(Wt::StandardButton result)
{
	delete m_messageBox;
	m_messageBox = 0;
}


void Download::performDownload()
{
	boost::uuids::basic_random_generator<boost::mt19937> gen;
	boost::uuids::uuid u = gen();

	std::stringstream ss;
	ss << u;

#if BOOST_FILESYSTEM_VERSION == 3
	path newPath = "./tmp/" + ss.str() + "/" + m_fileToDownload.filename().string();
#elif BOOST_FILESYSTEM_VERSION == 2
	string newPath = "./tmp/" + ss.str() + "/" + m_fileToDownload.filename();
#endif

	system(string("ln -s ${PWD}/" + m_fileToDownload.parent_path().string() + " /tmp/" + ss.str()).c_str());

	if (WApplication::instance()->environment().agentIsChrome())
	{
		m_messageBox  = new WMessageBox("Browser warnings",
					tr("home.download.browserWarning"),
					NoIcon, Ok);

		m_messageBox->buttonClicked().connect(this, &Download::messageBoxDone);

		m_messageBox->setOffsets(0, Bottom);

		m_messageBox->animateShow
		  (WAnimation(WAnimation::SlideInFromBottom
			  | WAnimation::Fade, WAnimation::Linear, 250));
	}

	WApplication::instance()->redirect(newPath.c_str());
}
